package com.yubo.yupicturebackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yubo.yupicturebackend.exception.ErrorCode;
import com.yubo.yupicturebackend.exception.ThrowUtils;
import com.yubo.yupicturebackend.model.dto.user.UserLoginRequest;
import com.yubo.yupicturebackend.model.dto.user.UserQueryRequest;
import com.yubo.yupicturebackend.model.dto.user.UserRegisterRequest;
import com.yubo.yupicturebackend.model.entity.User;
import com.yubo.yupicturebackend.model.enums.UserRoleEnum;
import com.yubo.yupicturebackend.model.vo.LoginUserVO;
import com.yubo.yupicturebackend.model.vo.UserVO;
import com.yubo.yupicturebackend.service.UserService;
import com.yubo.yupicturebackend.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.yubo.yupicturebackend.constant.UserConstant.USER_LOGIN_STATE;

/**
 * @author Seryer
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2024-12-28 13:35:15
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public long userRegister(UserRegisterRequest request) {
        // 1.校验参数
        ThrowUtils.throwIf(StrUtil.hasBlank(request.getUserAccount(), request.getUserPassword(), request.getCheckPassword())
                , ErrorCode.PARAMS_ERROR, "参数为空");
        ThrowUtils.throwIf(request.getUserPassword().length() < 8 || request.getCheckPassword().length() < 8
                , ErrorCode.PARAMS_ERROR, "密码长度不能小于8位");
        ThrowUtils.throwIf(request.getUserAccount().length() < 4
                , ErrorCode.PARAMS_ERROR, "用户账号长度不能小于4位");
        ThrowUtils.throwIf(!request.getUserPassword().equals(request.getCheckPassword())
                , ErrorCode.PARAMS_ERROR, "两次密码不一致");
        // 2.检查用户账户在数据库是否重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_account", request.getUserAccount());
        ThrowUtils.throwIf(this.baseMapper.selectCount(queryWrapper) > 0, ErrorCode.PARAMS_ERROR, "用户账户重复");
        // 3.密码加密
        String encryptPassword = getEncryptPassword(request.getUserPassword());
        // 4.插入数据到数据库中
        User user = new User();
        user.setUserAccount(request.getUserAccount());
        user.setUserPassword(encryptPassword);
        user.setUserName("无名氏");
        user.setUserRole(UserRoleEnum.USER.getValue());
        boolean save = this.save(user);
        ThrowUtils.throwIf(!save, ErrorCode.SYSTEM_ERROR, "注册失败");
        return user.getId();
    }

    @Override
    public LoginUserVO userLogin(UserLoginRequest request, HttpServletRequest httpServletRequest) {
        //1.校验
        ThrowUtils.throwIf(StrUtil.hasBlank(request.getUserAccount(), request.getUserPassword())
                , ErrorCode.PARAMS_ERROR, "参数为空");
        ThrowUtils.throwIf(request.getUserPassword().length() < 8
                , ErrorCode.PARAMS_ERROR, "密码错误");
        ThrowUtils.throwIf(request.getUserAccount().length() < 4
                , ErrorCode.PARAMS_ERROR, "账号错误");
        //2.对用户传递的密码进行加密
        String encryptPassword = getEncryptPassword(request.getUserPassword());
        //3.查询数据库中用户是否存在
        User user = this.baseMapper.selectOne(new QueryWrapper<User>().eq("user_account", request.getUserAccount())
                .eq("user_password", encryptPassword));
        //不存在抛异常
        ThrowUtils.throwIf(user == null, ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        //保存用户登录态
        httpServletRequest.getSession().setAttribute(USER_LOGIN_STATE, user);
        return this.getLoginUserVO(user);
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        User currentUser = (User) request.getSession().getAttribute(USER_LOGIN_STATE);
        ThrowUtils.throwIf(currentUser == null || currentUser.getId() == null, ErrorCode.NOT_LOGIN_ERROR);
        // 从数据库查询（追求性能的话可以注释，直接走缓存）
        currentUser = this.getById(currentUser.getId());
        ThrowUtils.throwIf(currentUser == null, ErrorCode.NOT_LOGIN_ERROR);
        return currentUser;
    }

    /**
     * 获取脱敏用户信息
     *
     * @param user
     * @return
     */
    @Override
    public LoginUserVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        return BeanUtil.copyProperties(user, LoginUserVO.class);
    }


    @Override
    public UserVO getUserVO(User user) {
        if (user == null) {
            return null;
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }

    @Override
    public List<UserVO> getUserVOList(List<User> userList) {
        if (CollUtil.isEmpty(userList)) {
            return new ArrayList<>();
        }
        return userList.stream().map(this::getUserVO).collect(Collectors.toList());
    }


    @Override
    public Boolean userLogout(HttpServletRequest request) {
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        ThrowUtils.throwIf(userObj == null, ErrorCode.OPERATION_ERROR, "未登录");
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    @Override
    public QueryWrapper<User> getQueryWrapper(UserQueryRequest userQueryRequest) {
        ThrowUtils.throwIf(userQueryRequest == null, ErrorCode.PARAMS_ERROR, "请求参数为空");
        Long id = userQueryRequest.getId();
        String userAccount = userQueryRequest.getUserAccount();
        String userName = userQueryRequest.getUserName();
        String userProfile = userQueryRequest.getUserProfile();
        String userRole = userQueryRequest.getUserRole();
        String sortField = userQueryRequest.getSortField();
        String sortOrder = userQueryRequest.getSortOrder();
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.eq(StrUtil.isNotBlank(userRole), "user_role", userRole);
        queryWrapper.like(StrUtil.isNotBlank(userAccount), "user_account", userAccount);
        queryWrapper.like(StrUtil.isNotBlank(userName), "user_name", userName);
        queryWrapper.like(StrUtil.isNotBlank(userProfile), "user_profile", userProfile);
        queryWrapper.orderBy(StrUtil.isNotEmpty(sortField), sortOrder.equals("ascend"), sortField);
        return queryWrapper;
    }



    @Override
    public String getEncryptPassword(String password) {
        // 加盐
        final String salt = "yubo";
        return DigestUtils.md5DigestAsHex((salt + password).getBytes());

    }

    @Override
    public boolean isAdmin(User user) {
        return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole());
    }


    public static class OllamaStreamReceiver {
        OkHttpClient client = new OkHttpClient.Builder()
                .readTimeout(0, TimeUnit.MILLISECONDS) // 禁用读取超时，确保可以长时间读取流数据
                .build();

        public void run() throws Exception {
            MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
            String jsonPayload = "{\n    \"model\": \"deepseek-r1:1.5b\",\n    \"prompt\": \"叶莹是谁?\"\n}";
            RequestBody body = RequestBody.create(mediaType, jsonPayload);

            Request request = new Request.Builder()
                    .url("http://localhost:11434/api/generate")
                    .post(body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            final int[] count = {1};
            client.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (!response.isSuccessful()) {
                        throw new IOException("Unexpected code " + response);
                    }

                    try (ResponseBody responseBody = response.body()) {
                        if (responseBody != null) {
                            BufferedSource source = responseBody.source();
                            while (!source.exhausted()) {
                                System.out.println(count[0]++);
                                String line = source.readUtf8Line();
                                JSONObject jsonObject = JSONUtil.parseObj(line);
                                System.out.println(source.exhausted());
                                if (line != null) {
                                    // 处理每行数据
                                    System.out.println(line);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    public static void main(String[] args) throws Exception {
        OllamaStreamReceiver ollamaStreamReceiver = new OllamaStreamReceiver();
        ollamaStreamReceiver.run();
        System.out.println("done *************");
    }

}




